package org.xx.armory.commons;

import static org.apache.commons.lang3.CharUtils.isAsciiPrintable;
import static org.apache.commons.lang3.CharUtils.unicodeEscaped;

/**
 * @author Haart
 */
public final class StringComparisonResult {
    /**
     * 不存在任何不同之处的比较结果
     */
    static final StringComparisonResult NONE = new StringComparisonResult(-1, null, null);
    private final int diffPos;
    private final Character ch1;
    private final Character ch2;

    /**
     * 表示两个字符串不相同之处的对象。
     *
     * @param diffPos
     *         不相同之处的下标，从{@code 0}开始。
     * @param ch1
     *         第一个字符串的字符。
     * @param ch2
     *         第二个字符串的字符。
     */
    private StringComparisonResult(
            final int diffPos,
            final Character ch1,
            final Character ch2
    ) {
        this.diffPos = diffPos;
        this.ch1 = ch1;
        this.ch2 = ch2;
    }

    /**
     * 构造一个{@code StringComparisonResult}对象。
     *
     * @param diffPos
     *         不相同之处的下标，从{@code 0}开始。
     * @param ch1
     *         第一个字符串的字符。
     * @param ch2
     *         第二个字符串的字符。
     * @return 根据指定参数构造的{@code StringComparisonResult}对象。
     */
    public static StringComparisonResult of(
            final int diffPos,
            final Character ch1,
            final Character ch2
    ) {
        return new StringComparisonResult(diffPos, ch1, ch2);
    }

    /**
     * 格式化字符。
     *
     * @param ch
     *         待格式化的字符。
     * @return 格式化结果。如果参数{@code ch}是{@code null}则返回空字符串。
     */
    private static String formatCh(final Character ch) {
        return ch != null ? isAsciiPrintable(ch) ?
                "'" + ch + "'(" + unicodeEscaped(ch) + ")" :
                "<?>(" + unicodeEscaped(ch) + ")" :
                "";
    }

    public static void main(String[] args) {
        System.out.println(new StringComparisonResult(3, null, '中'));
    }

    /**
     * 是否不存在不同之处。
     *
     * @return 如果不存在不同之处则返回{@code true}，否则返回{@code false}。
     */
    public final boolean isSame() {
        return this.diffPos < 0;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public final String toString() {
        if (this.diffPos < 0) {
            return "no diff";
        } else {
            return "diff at [" + diffPos + "] " + formatCh(ch1) + " != " + formatCh(ch2);
        }
    }
}
